home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / gpt32src.zip / UTIL.C < prev    next >
C/C++ Source or Header  |  1992-03-25  |  13KB  |  609 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: util.c,v 3.26 92/03/24 22:34:43 woo Exp Locker: woo $";
  3. #endif
  4.  
  5. /* GNUPLOT - util.c */
  6. /*
  7.  * Copyright (C) 1986, 1987, 1990, 1991, 1992   Thomas Williams, Colin Kelley
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted, 
  11.  * provided that the above copyright notice appear in all copies and 
  12.  * that both that copyright notice and this permission notice appear 
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the modified code.  Modifications are to be distributed 
  17.  * as patches to released version.
  18.  *  
  19.  * This software is provided "as is" without express or implied warranty.
  20.  * 
  21.  *
  22.  * AUTHORS
  23.  * 
  24.  *   Original Software:
  25.  *     Thomas Williams,  Colin Kelley.
  26.  * 
  27.  *   Gnuplot 2.0 additions:
  28.  *       Russell Lang, Dave Kotz, John Campbell.
  29.  *
  30.  *   Gnuplot 3.0 additions:
  31.  *       Gershon Elber and many others.
  32.  * 
  33.  * Send your comments or suggestions to 
  34.  *  info-gnuplot@ames.arc.nasa.gov.
  35.  * This is a mailing list; to join it send a note to 
  36.  *  info-gnuplot-request@ames.arc.nasa.gov.  
  37.  * Send bug reports to
  38.  *  bug-gnuplot@ames.arc.nasa.gov.
  39.  */
  40.  
  41. #include <ctype.h>
  42. #include <setjmp.h>
  43. #include <stdio.h>
  44. #include <errno.h>
  45. #include "plot.h"
  46.  
  47. BOOLEAN screen_ok;
  48.     /* TRUE if command just typed; becomes FALSE whenever we
  49.         send some other output to screen.  If FALSE, the command line
  50.         will be echoed to the screen before the ^ error message. */
  51.  
  52. #ifndef vms
  53. #ifndef __ZTC__
  54. extern int errno;
  55. extern int sys_nerr;
  56. extern char *sys_errlist[];
  57. #endif
  58. #endif /* vms */
  59.  
  60. extern char input_line[];
  61. extern struct lexical_unit token[];
  62. extern jmp_buf env;    /* from plot.c */
  63. extern int inline_num;        /* from command.c */
  64. extern BOOLEAN interactive;    /* from plot.c */
  65. extern char *infile_name;    /* from plot.c */
  66.  
  67. extern char *strchr();
  68.  
  69. #ifndef AMIGA_AC_5
  70. extern double sqrt(), atan2();
  71. #endif
  72.  
  73. /*
  74.  * chr_in_str() compares the characters in the string of token number t_num
  75.  * with c, and returns TRUE if a match was found.
  76.  */
  77. chr_in_str(t_num, c)
  78. int t_num;
  79. char c;
  80. {
  81. register int i;
  82.  
  83.     if (!token[t_num].is_token)
  84.         return(FALSE);                /* must be a value--can't be equal */
  85.     for (i = 0; i < token[t_num].length; i++) {
  86.         if (input_line[token[t_num].start_index+i] == c)
  87.             return(TRUE);
  88.         }
  89.     return FALSE;
  90. }
  91.  
  92.  
  93. /*
  94.  * equals() compares string value of token number t_num with str[], and
  95.  *   returns TRUE if they are identical.
  96.  */
  97. equals(t_num, str)
  98. int t_num;
  99. char *str;
  100. {
  101. register int i;
  102.  
  103.     if (!token[t_num].is_token)
  104.         return(FALSE);                /* must be a value--can't be equal */
  105.     for (i = 0; i < token[t_num].length; i++) {
  106.         if (input_line[token[t_num].start_index+i] != str[i])
  107.             return(FALSE);
  108.         }
  109.     /* now return TRUE if at end of str[], FALSE if not */
  110.     return(str[i] == '\0');
  111. }
  112.  
  113.  
  114.  
  115. /*
  116.  * almost_equals() compares string value of token number t_num with str[], and
  117.  *   returns TRUE if they are identical up to the first $ in str[].
  118.  */
  119. almost_equals(t_num, str)
  120. int t_num;
  121. char *str;
  122. {
  123. register int i;
  124. register int after = 0;
  125. register start = token[t_num].start_index;
  126. register length = token[t_num].length;
  127.  
  128.     if (!token[t_num].is_token)
  129.         return(FALSE);                /* must be a value--can't be equal */
  130.     for (i = 0; i < length + after; i++) {
  131.         if (str[i] != input_line[start + i]) {
  132.             if (str[i] != '$')
  133.                 return(FALSE);
  134.             else {
  135.                 after = 1;
  136.                 start--;    /* back up token ptr */
  137.                 }
  138.             }
  139.         }
  140.  
  141.     /* i now beyond end of token string */
  142.  
  143.     return(after || str[i] == '$' || str[i] == '\0');
  144. }
  145.  
  146.  
  147.  
  148. isstring(t_num)
  149. int t_num;
  150. {
  151.     
  152.     return(token[t_num].is_token &&
  153.            (input_line[token[t_num].start_index] == '\'' ||
  154.            input_line[token[t_num].start_index] == '\"'));
  155. }
  156.  
  157.  
  158. isnumber(t_num)
  159. int t_num;
  160. {
  161.     return(!token[t_num].is_token);
  162. }
  163.  
  164.  
  165. isletter(t_num)
  166. int t_num;
  167. {
  168.     return(token[t_num].is_token &&
  169.             ((isalpha(input_line[token[t_num].start_index]))||
  170.              (input_line[token[t_num].start_index] == '_')));
  171. }
  172.  
  173.  
  174. /*
  175.  * is_definition() returns TRUE if the next tokens are of the form
  176.  *   identifier =
  177.  *        -or-
  178.  *   identifier ( identifer ) =
  179.  */
  180. is_definition(t_num)
  181. int t_num;
  182. {
  183.     return (isletter(t_num) &&
  184.             (equals(t_num+1,"=") ||            /* variable */
  185.             (equals(t_num+1,"(") &&        /* function */
  186.              isletter(t_num+2)   &&
  187.              equals(t_num+3,")") &&
  188.              equals(t_num+4,"=") ) ||
  189.             (equals(t_num+1,"(") &&        /* function with */
  190.              isletter(t_num+2)   &&        /* two variables */
  191.              equals(t_num+3,",") &&
  192.              isletter(t_num+4)   &&
  193.              equals(t_num+5,")") &&
  194.              equals(t_num+6,"=") )
  195.         ));
  196. }
  197.  
  198.  
  199.  
  200. /*
  201.  * copy_str() copies the string in token number t_num into str, appending
  202.  *   a null.  No more than MAX_ID_LEN chars are copied.
  203.  */
  204. copy_str(str, t_num)
  205. char str[];
  206. int t_num;
  207. {
  208. register int i = 0;
  209. register int start = token[t_num].start_index;
  210. register int count;
  211.  
  212.     if ((count = token[t_num].length) > MAX_ID_LEN)
  213.         count = MAX_ID_LEN;
  214.     do {
  215.         str[i++] = input_line[start++];
  216.         } while (i != count);
  217.     str[i] = '\0';
  218. }
  219.  
  220.  
  221. /*
  222.  * quote_str() does the same thing as copy_str, except it ignores the
  223.  *   quotes at both ends.  This seems redundant, but is done for
  224.  *   efficency.
  225.  */
  226. quote_str(str, t_num)
  227. char str[];
  228. int t_num;
  229. {
  230. register int i = 0;
  231. register int start = token[t_num].start_index + 1;
  232. register int count;
  233.  
  234.     if ((count = token[t_num].length - 2) > MAX_ID_LEN)
  235.         count = MAX_ID_LEN;
  236.     if (count>0) {
  237.         do {
  238.             str[i++] = input_line[start++];
  239.             } while (i != count);
  240.     }
  241.     str[i] = '\0';
  242. }
  243.  
  244.  
  245. /*
  246.  * quotel_str() does the same thing as quote_str, except it uses
  247.  * MAX_LINE_LEN instead of MAX_ID_LEN. 
  248.  */ 
  249. quotel_str(str, t_num) 
  250. char str[]; 
  251. int t_num; 
  252. {
  253. register int i = 0;
  254. register int start = token[t_num].start_index + 1;
  255. register int count;
  256.  
  257.     if ((count = token[t_num].length - 2) > MAX_LINE_LEN)
  258.         count = MAX_LINE_LEN;
  259.     if (count>0) {
  260.         do {
  261.             str[i++] = input_line[start++];
  262.             } while (i != count);
  263.     }
  264.     str[i] = '\0';
  265. }
  266.  
  267.  
  268. /*
  269.  *    capture() copies into str[] the part of input_line[] which lies between
  270.  *    the begining of token[start] and end of token[end].
  271.  */
  272. capture(str,start,end)
  273. char str[];
  274. int start,end;
  275. {
  276. register int i,e;
  277.  
  278.     e = token[end].start_index + token[end].length;
  279.     for (i = token[start].start_index; i < e && input_line[i] != '\0'; i++)
  280.         *str++ = input_line[i];
  281.     *str = '\0';
  282. }
  283.  
  284.  
  285. /*
  286.  *    m_capture() is similar to capture(), but it mallocs storage for the
  287.  *  string.
  288.  */
  289. m_capture(str,start,end)
  290. char **str;
  291. int start,end;
  292. {
  293. register int i,e;
  294. register char *s;
  295.  
  296.     if (*str)        /* previous pointer to malloc'd memory there */
  297.         free(*str);
  298.     e = token[end].start_index + token[end].length;
  299.     *str = alloc((unsigned int)(e - token[start].start_index + 1), "string");
  300.      s = *str;
  301.      for (i = token[start].start_index; i < e && input_line[i] != '\0'; i++)
  302.       *s++ = input_line[i];
  303.      *s = '\0';
  304. }
  305.  
  306.  
  307. /*
  308.  *    m_quote_capture() is similar to m_capture(), but it removes
  309.     quotes from either end if the string.
  310.  */
  311. m_quote_capture(str,start,end)
  312. char **str;
  313. int start,end;
  314. {
  315. register int i,e;
  316. register char *s;
  317.  
  318.     if (*str)        /* previous pointer to malloc'd memory there */
  319.         free(*str);
  320.     e = token[end].start_index + token[end].length-1;
  321.     *str = alloc((unsigned int)(e - token[start].start_index + 1), "string");
  322.      s = *str;
  323.     for (i = token[start].start_index + 1; i < e && input_line[i] != '\0'; i++)
  324.      *s++ = input_line[i];
  325.     *s = '\0';
  326. }
  327.  
  328.  
  329. convert(val_ptr, t_num)
  330. struct value *val_ptr;
  331. int t_num;
  332. {
  333.     *val_ptr = token[t_num].l_val;
  334. }
  335.  
  336. static char *num_to_str(r)
  337. double r;
  338. {
  339.     static i = 0;
  340.     static char s[4][20];
  341.     int j = i++;
  342.  
  343.     if ( i > 3 ) i = 0;
  344.  
  345.     sprintf( s[j], "%g", r );
  346.     if ( strchr( s[j], '.' ) == NULL &&
  347.          strchr( s[j], 'e' ) == NULL &&
  348.          strchr( s[j], 'E' ) == NULL )
  349.         strcat( s[j], ".0" );
  350.  
  351.     return s[j];
  352.  
  353. disp_value(fp,val)
  354. FILE *fp;
  355. struct value *val;
  356. {
  357.     switch(val->type) {
  358.         case INT:
  359.             fprintf(fp,"%d",val->v.int_val);
  360.             break;
  361.         case CMPLX:
  362.             if (val->v.cmplx_val.imag != 0.0 )
  363.                 fprintf(fp,"{%s, %s}",
  364.                     num_to_str(val->v.cmplx_val.real),
  365.                     num_to_str(val->v.cmplx_val.imag));
  366.             else
  367.                 fprintf(fp,"%s",
  368.                     num_to_str(val->v.cmplx_val.real));
  369.             break;
  370.         default:
  371.             int_error("unknown type in disp_value()",NO_CARET);
  372.     }
  373. }
  374.  
  375.  
  376. double
  377. real(val)        /* returns the real part of val */
  378. struct value *val;
  379. {
  380.     switch(val->type) {
  381.         case INT:
  382.             return((double) val->v.int_val);
  383.         case CMPLX:
  384.             return(val->v.cmplx_val.real);
  385.     }
  386.     int_error("unknown type in real()",NO_CARET);
  387.     /* NOTREACHED */
  388.     return((double)0.0);
  389. }
  390.  
  391.  
  392. double
  393. imag(val)        /* returns the imag part of val */
  394. struct value *val;
  395. {
  396.     switch(val->type) {
  397.         case INT:
  398.             return(0.0);
  399.         case CMPLX:
  400.             return(val->v.cmplx_val.imag);
  401.     }
  402.     int_error("unknown type in imag()",NO_CARET);
  403.     /* NOTREACHED */
  404.     return((double)0.0);
  405. }
  406.  
  407.  
  408.  
  409. double
  410. magnitude(val)        /* returns the magnitude of val */
  411. struct value *val;
  412. {
  413.     switch(val->type) {
  414.         case INT:
  415.             return((double) abs(val->v.int_val));
  416.         case CMPLX:
  417.             return(sqrt(val->v.cmplx_val.real*
  418.                     val->v.cmplx_val.real +
  419.                     val->v.cmplx_val.imag*
  420.                     val->v.cmplx_val.imag));
  421.     }
  422.     int_error("unknown type in magnitude()",NO_CARET);
  423.     /* NOTREACHED */
  424.     return((double)0.0);
  425. }
  426.  
  427.  
  428.  
  429. double
  430. angle(val)        /* returns the angle of val */
  431. struct value *val;
  432. {
  433.     switch(val->type) {
  434.         case INT:
  435.             return((val->v.int_val > 0) ? 0.0 : Pi);
  436.         case CMPLX:
  437.             if (val->v.cmplx_val.imag == 0.0) {
  438.                 if (val->v.cmplx_val.real >= 0.0)
  439.                     return(0.0);
  440.                 else
  441.                     return(Pi);
  442.             }
  443.             return(atan2(val->v.cmplx_val.imag,
  444.                      val->v.cmplx_val.real));
  445.     }
  446.     int_error("unknown type in angle()",NO_CARET);
  447.     /* NOTREACHED */
  448.     return((double)0.0);
  449. }
  450.  
  451.  
  452. struct value *
  453. complex(a,realpart,imagpart)
  454. struct value *a;
  455. double realpart, imagpart;
  456. {
  457.     a->type = CMPLX;
  458.     a->v.cmplx_val.real = realpart;
  459.     a->v.cmplx_val.imag = imagpart;
  460.     return(a);
  461. }
  462.  
  463.  
  464. struct value *
  465. integer(a,i)
  466. struct value *a;
  467. int i;
  468. {
  469.     a->type = INT;
  470.     a->v.int_val = i;
  471.     return(a);
  472. }
  473.  
  474.  
  475.  
  476. os_error(str,t_num)
  477. char str[];
  478. int t_num;
  479. {
  480. #ifdef vms
  481. static status[2] = {1, 0};        /* 1 is count of error msgs */
  482. #endif
  483.  
  484. register int i;
  485.  
  486.     /* reprint line if screen has been written to */
  487.  
  488.     if (t_num != NO_CARET) {        /* put caret under error */
  489.         if (!screen_ok)
  490.             fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
  491.  
  492.         for (i = 0; i < sizeof(PROMPT) - 1; i++)
  493.             (void) putc(' ',stderr);
  494.         for (i = 0; i < token[t_num].start_index; i++) {
  495.             (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  496.             }
  497.         (void) putc('^',stderr);
  498.         (void) putc('\n',stderr);
  499.     }
  500.  
  501.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  502.         (void) putc(' ',stderr);
  503.     fprintf(stderr,"%s\n",str);
  504.  
  505.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  506.         (void) putc(' ',stderr);
  507.      if (!interactive)
  508.       if (infile_name != NULL)
  509.         fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
  510.       else
  511.         fprintf(stderr,"line %d: ", inline_num);
  512.  
  513.  
  514. #ifdef vms
  515.     status[1] = vaxc$errno;
  516.     sys$putmsg(status);
  517.     (void) putc('\n',stderr);
  518. #else
  519. #ifdef __ZTC__
  520.     fprintf(stderr,"error number %d\n\n",errno);
  521. #else
  522.     if (errno >= sys_nerr)
  523.         fprintf(stderr, "unknown errno %d\n\n", errno);
  524.     else
  525.         fprintf(stderr,"(%s)\n\n",sys_errlist[errno]);
  526. #endif
  527. #endif
  528.  
  529.     longjmp(env, TRUE);    /* bail out to command line */
  530. }
  531.  
  532.  
  533. int_error(str,t_num)
  534. char str[];
  535. int t_num;
  536. {
  537. register int i;
  538.  
  539.     /* reprint line if screen has been written to */
  540.  
  541.     if (t_num != NO_CARET) {        /* put caret under error */
  542.         if (!screen_ok)
  543.             fprintf(stderr,"\n%s%s\n", PROMPT, input_line);
  544.  
  545.         for (i = 0; i < sizeof(PROMPT) - 1; i++)
  546.             (void) putc(' ',stderr);
  547.         for (i = 0; i < token[t_num].start_index; i++) {
  548.             (void) putc((input_line[i] == '\t') ? '\t' : ' ',stderr);
  549.             }
  550.         (void) putc('^',stderr);
  551.         (void) putc('\n',stderr);
  552.     }
  553.  
  554.     for (i = 0; i < sizeof(PROMPT) - 1; i++)
  555.         (void) putc(' ',stderr);
  556.      if (!interactive)
  557.       if (infile_name != NULL)
  558.         fprintf(stderr,"\"%s\", line %d: ", infile_name, inline_num);
  559.       else
  560.         fprintf(stderr,"line %d: ", inline_num);
  561.      fprintf(stderr,"%s\n\n", str);
  562.  
  563.     longjmp(env, TRUE);    /* bail out to command line */
  564. }
  565.  
  566. /* Lower-case the given string (DFK) */
  567. /* Done in place. */
  568. void
  569. lower_case(s)
  570.      char *s;
  571. {
  572.   register char *p = s;
  573.  
  574.   while (*p != '\0') {
  575.     if (isupper(*p))
  576.      *p = tolower(*p);
  577.     p++;
  578.   }
  579. }
  580.  
  581. /* Squash spaces in the given string (DFK) */
  582. /* That is, reduce all multiple white-space chars to single spaces */
  583. /* Done in place. */
  584. void
  585. squash_spaces(s)
  586.      char *s;
  587. {
  588.   register char *r = s;        /* reading point */
  589.   register char *w = s;        /* writing point */
  590.   BOOLEAN space = FALSE;        /* TRUE if we've already copied a space */
  591.  
  592.   for (w = r = s; *r != '\0'; r++) {
  593.      if (isspace(*r)) {
  594.         /* white space; only copy if we haven't just copied a space */
  595.         if (!space) {
  596.             space = TRUE;
  597.             *w++ = ' ';
  598.         }                /* else ignore multiple spaces */
  599.      } else {
  600.         /* non-space character; copy it and clear flag */
  601.         *w++ = *r;
  602.         space = FALSE;
  603.      }
  604.   }
  605.   *w = '\0';                /* null terminate string */
  606. }
  607.  
  608.